" echom "提示：This is functions-user.vimrc"

"===============================================================================
" 自定义函数配置

""""""""""""  自定义函数: 切换工作空间
""""""""""""  

	"function Cw(dir)
	"    execute ":cd  ".a:dir
	"endfunction

	" 使用说明：
		" 命令模式下输入 ：call Cw(prj_2) 快速切换到项目空间(前提是在配置里定义了prj_2的路径)

	" 配置例子1：
		" let g:prj_1 = "~/Desktop/tmp/prj_1" 
		" let g:prj_2 = "~/Desktop/tmp/prj_2"
		" let g:WorkDir = "~/tmp"  "相对路径写法  意为当前用户下的tmp目录
		" call Cw(WorkDir)
	" 配置例子2：
		" let g:MyWorkSpace = "C:/MyWorkSpace"
		" let g:CodeStudio = g:MyWorkSpace."/GitHub_Prj/"
		" call Cw(CodeStudio)

	"" 实际配置：
		" let g:WorkDir = "D:\MyWorkSpace"
		" call Cw(WorkDir)



""""""""""""  自定义函数: 快速输入时间
""""""""""""  

	" --实现方案一, 然后在编辑文件时，在输入模式下，输入 xdate 或 xdatetime 后按回车，便可输入以下格式的时间：
		iab xdate <c-r>=strftime("20%y.%m.%d")<cr> 
		iab xdatetime <c-r>=strftime("20%y/%m/%d %H:%M:%S")<cr> 
		iab xdatetime1 <c-r>=strftime("20%y/%m/%d %H:%M:%S %p (%A) %z")<cr> 

	" --实现方案二, linux系统的命令模式下 :r !date 

	" --实现方案三,
	" 返回当前时间
	func! GetTimeInfo()
		"return strftime('%Y-%m-%d %A %H:%M:%S')
		return strftime('%Y-%m-%d %H:%M:%S')
	endfunction

	" 插入模式按 Ctrl + D(ate) 插入当前时间
	imap <C-d> <C-r>=GetTimeInfo()<cr>

	" > 参考资料
	" + [Vim技能修炼教程(15) - 时间和日期相关函数](https://www.jianshu.com/p/172982c0a5f4)

""""""""""""  自定义函数: 获取当前目录路径
""""""""""""  

	" 将当前编辑的文件完全路径拷贝到系统剪贴板 --实现方案一
		" function GetCurFilePath()
		"     let cur_dir=getcwd()
		"     let dir_filename=cur_dir."\\"
		"     echo dir_filename.expand("%:r")."         done"
		"     call setreg('+',dir_filename)
		" endfunction

	" 将当前编辑的文件完全路径拷贝到系统剪贴板  --实现方案二
		function GetCurFilePath()
			" let cur_dir=getcwd() "
			let cur_file_path = getreg('%')
			" let dir_filename=cur_dir."\\".cur_file_name
			echom "复制当前路径[".cur_file_path."]到系统剪贴板[寄存器+]中"
			call setreg('+',cur_file_path)
		endfunction

	" 使用说明
		" 命令模式下输入 ：call GetCurFilePath() 快速获取当前路径

	" 快捷键设置
	"nnoremap <silent> <F9> : call GetCurFilePath()<cr>


""""""""""""  自定义函数:设置只有在是PHP文件时，才启用PHP补全 函数
""""""""""""  

	" 前提
		" 1、 配置步骤：首先下载PHP函数列表文件，将该文件保存在目录 /etc/vim/下:
		" 2、 设置php函数列表文件地址（前提将php_funclist.txt文件放在 ~/php_funclist.txt ）

	" 设置在针对所有文件都启用了PHP补全
	" 将函数列表文件引入补全配置中
	" set dictionary-=/etc/vim/php_funclist.txt  dictionary+=/etc/vim/php_funclist.txt
	" set dictionary-='C:/Program Files (x86)/Vim/vimfiles/php_funclist.txt'  dictionary+='C:/Program Files (x86)/Vim/vimfiles/php_funclist.txt'

	" 设置只有在是PHP文件时，才启用PHP补全
	au FileType php call PHPFuncList()

	function PHPFuncList()
		set dictionary-=~/.vim/completion_dictionary/php_funclist.txt dictionary+=~/.vim/completion_dictionary/php_funclist.txt
		set complete-=k complete+=k
	endfunction

	" 使用方法
		" 进入vim编辑的时候，按下 (control+p)或者 ，就可以出现php的自动补全。

""""""""""""  自定义函数:用其他应用打开当前文件夹
""""""""""""  

	"功能：用其他应用打开当前文件夹，同时不阻塞当前窗口。

	function OpenFolderWithAnotherApp(name)
		let path = expand("%:p:h")
		echom "当前位置：" . path
		if(has("win32") || has("win64") || has("win95") || has("win16"))
			let l:apps = {
				\"Explorer":"explorer \/select, %:p:h",
				\"PowerShell":"powershell.exe -noexit -command Set-Location -literalPath  %:p:h",
				\"Git-Gui":"C:\\Program Files\\Git\\cmd\\git-gui.exe  --working-dir %:p:h",
				\"Git-Bash":"C:\\Program Files\\Git\\git-bash.exe --cd=%:p:h",
				\}

			"C:\Program Files\Git\cmd\git-gui.exe" "--working-dir" "%1"
			"powershell.exe -noexit -command Set-Location -literalPath '%V'
			"C:\Users\CodeRooster\AppData\Local\Programs\Microsoft VS Code\Code.exe" "%V"
			"C:\Program Files\Git\git-bash.exe" "--cd=%1"

			" 执行命令用相应程序打开文件
			execute "!start "l:apps[a:name]
		else
			let l:apps = {
				\"thunar":"thunar %:p:h",
				\"uget":"uget-gtk",
				\"netease-cloud-music":"netease-cloud-music",
				\}
			" 执行命令用相应程序打开文件
			execute "silent !"  l:apps[a:name]
		endif
	endfunction
	" 快捷方式映射
	if(isWindows) 
		" map gb <ESC>:call OpenFolderWithAnotherApp("Explorer")<CR>
	endif

	" 使用说明
		" 命令模式下 输入: call OpenFolderWithAnotherApp("应用列表中的应用名") 

	" 自定命令
	if(isWindows)
		:command Explorer   :call OpenFolderWithAnotherApp("Explorer")          " 用文件管理器打开
		:command PowerShell :call OpenFolderWithAnotherApp("PowerShell")        " 在PowerShell打开
		:command Gitbash    :call OpenFolderWithAnotherApp("Git-Bash")          " 用Git-Bash打开
		:command Gitgui     :call OpenFolderWithAnotherApp("Git-Gui")           " 用Git-Gui打开
	endif

	if(isLinux)
		:command Thunar      :call OpenFolderWithAnotherApp("thunar")             " 图形文件管理器Thunar
		:command Uget        :call OpenFolderWithAnotherApp("uget")               " 打开下载软件uget
		:command Ncloudmusic :call OpenFolderWithAnotherApp("netease-cloud-music") " 打开网易云音乐
	endif

""""""""""""  自定义函数:使用系统上的软件打开当前文件
""""""""""""  

	" 功能：使用第三方软件快速打开当前文件，同时不阻塞当前窗口。
		" 例： 日志实时查看 BareTailProfessional 打开文件
		"        chrome、firefox浏览器打开预览

	function OpenFileWithAnotherApp(name)
		let file = expand("%:p")
		echom "当前文件：" . file

		if(has("win32") || has("win64") || has("win95") || has("win16"))
			let l:apps = {
				\"gvim":"gvim",
				\"Chrome":"C\:\\Program Files\ \(x86\)\\Google\\Chrome\\Application\\chrome.exe",
				\"FireFox":"C\:\\Program\ Files\\Mozilla\ Firefox\\firefox.exe",
				\"sublime_text3":"D:\\XWindowsToolSoftware\\Tool_Sublime_Text3_for_Windows\\SublimeText3\\sublime_text.exe",
				\"Notepad++":"C:\\Program\ Files\ \(x86\)\\Notepad++\\notepad++.exe",
				\"baregreppro":"D:\\XWindowsToolSoftware\\BareTailProfessional\\baregreppro.exe",
				\"baretailpro":"D:\\XWindowsToolSoftware\\BareTailProfessional\\baretailpro.exe",
				\"Typora":"C:\\Program Files\\Typora\\Typora.exe",
			\}
			" 执行命令用相应程序打开文件
			execute "!start "  l:apps[a:name] file
		else
			let l:apps = {
				\"gvim":"gvim",
				\"Chromium":"chromium",
				\"FireFox":"firefox",
				\"sublime_text3":"sublime-text",
				\"Typora":"typora",
				\}
			" 执行命令用相应程序打开文件
			execute "silent !"  l:apps[a:name] file
		endif
	endfunction

	" 命令映射
	if(isWindows)
		:command Gvim        :call OpenFileWithAnotherApp("gvim")          " 用Gvim再打开
		:command Chrome      :call OpenFileWithAnotherApp("Chrome")        " 用谷歌浏览器打开 
		:command Firefox     :call OpenFileWithAnotherApp("FireFox")       " 用火狐浏览器打开
		:command Baretail    :call OpenFileWithAnotherApp("baretailpro")   " 用日志文件实时查看软件器Baretailpro打开当前文件
		:command Baregrep    :call OpenFileWithAnotherApp("baregreppro")   " 用日志文件检索实时查看器baregreppr打开当前文件
		:command Sublime     :call OpenFileWithAnotherApp("sublime_text3") " 用sublime_text3打开当前文件
		:command Notepad     :call OpenFileWithAnotherApp("Notepad++")     " 用sublime_text3打开当前文件
		:command Typora      :call OpenFileWithAnotherApp("Typora")        " 用MarkDown编辑查看器Typora打开
	endif

	if(isLinux)
		:command Gvim        :call OpenFileWithAnotherApp("gvim")          " 用Gvim再打开
		:command Chromium    :call OpenFileWithAnotherApp("Chromium")      " 用谷歌浏览器打开 
		:command Firefox     :call OpenFileWithAnotherApp("FireFox")       " 用火狐浏览器打开
		:command Typora      :call OpenFileWithAnotherApp("Typora")        " 用MarkDown编辑查看器Typora打开
		command -nargs=? Sudow :w !sudo tee %                              " 保存时，用命令:w !sudo tee % 使用root权限保存
	endif

	" >参考资料
		" + [VIM 浏览器预览插件](https://mikecoder.cn/post/190/)
		" + [笨方法学Vimscript](https://www.kancloud.cn/kancloud/learn-vimscript-the-hard-way/49291)"


""""""""""""  自定义函数: 搜索当前光标位置的词
""""""""""""  
	" 知识点

	" 第一，多文件查找
		" vimgrep是vim自带的一个工具，类似于grep的用法就可以实现。比如要在当前目录查找word，使用如下：
		"     :vimgrep word *
		"
		" 如果想要递归查找所有下级目录里面，那么就用
		"     :vimgrep word **

	" 第二，多文件替换
		" 实际上只要如下两个命令即可（假设要将当前目录下所有扩展名为.txt/.cpp的文件中的hate替换成love）:
		" :args *.txt *.cpp
		" :argdo %s/hate/love/gc | update
		" 就可以完成啦。
		
		" 解释如下，
		" :args *.txt *.cpp
		" 这样写会扫描当前目录下的.txt 和 .cpp文件，并加入到参数列表。但是这样写只会扫描当前目录，
		"
		" 如果想要递归扫描所有下级目录的话，用
		" :args **/*.txt
		" 
		" 如果只想扫描下一级目录（即不扫描当前目录）的话，用
		" :args */*.txt
		" 而
		" :argdo %s/hate/love/gc | update
		" 是将参数列表中的所有文件的hate提换成love，并写入硬盘（如果没有|update，就不会写入，但相应的替换也会被中断）。
	
		function Search_Word()
			" 在当前光标位置抓词
			let getWord = expand("<cword>")
			" 获取当前文件目录地址
			let path = expand("%:p:h")
			" 切换到当前位置目录下，防止执行时，目录定位再别处
			execute ":cd %:p:h "              
			echom "当前目录[".path."]下递归查找关键词[ ".getWord." ]" 
			execute "vimgrep ".getWord." **"
		endfunction

		" map fw :call Search_Word()<CR>:copen<CR>
	nnoremap <Leader>fs :call Search_Word()<CR>:copen<CR>
	" nnoremap <Leader>fs :call Search_Word()<CR>


	" 最后强调一点，使用替换命令的时候，一定记得备份，因为替换是直接写入硬盘滴哦……
		
	" > 参考资料
		" + [Vim(gvim)实现多文件的查找和替换](https://www.vimer.cn/2009/10/22/vim-gvim-shi-xian-duo-wen-jian-de-cha-zhao-he-ti-huan/)
		
""""""""""""  自定义函数: 生成PlantUML
""""""""""""  
	" 依赖
		" Java
		" plantuml.jar
		"
	" 知识点
	
	function XPlantUML(format)
		let file = expand("%:p")
		echom "当前文件：" . file
		" plantuml.jar路径
		let plantumlpath = g:myPlugPath."/vim-slumlord/plantuml.jar"
		" ArchLinux
		" let plantumlpath = '/usr/share/java/plantuml/plantuml.jar'
		
		let l:formats = {
			\"png":"png",
			\"svg":"svg",
			\}

		if(g:isWindows)
			let l:apps = {
				\"Chrome":"C\:\\Program Files\ \(x86\)\\Google\\Chrome\\Application\\chrome.exe",
				\"FireFox":"C\:\\Program\ Files\\Mozilla\ Firefox\\firefox.exe",
			\}
			" 执行命令，将当前文件按PlantUML语法生成png图片
			" execute "!start  java -jar ".plantumlpath  file
			" 执行命令，将当前文件按PlantUML语法生成svg
			echom "执行命令，将当前文件".file."按PlantUML语法生成".l:formats[a:format]
			" execute "!start  java -jar ".plantumlpath." -tsvg" file
			execute "!start  java -jar ".plantumlpath." -t".l:formats[a:format] file
		endif
		if(g:isLinux)
			let l:apps = {
				\"Chromium":"chromium",
				\"FireFox":"firefox",
				\}
			" 执行命令，将当前文件按PlantUML语法生成svg
			" execute "silent ! java -jar ".plantumlpath." -tsvg" file
			echom "执行命令，将当前文件".file."按PlantUML语法生成".l:formats[a:format]
			execute "silent ! java -jar ".plantumlpath." -t".l:formats[a:format] file
		endif
	endfunction

	function XPlantUMLViewer(format,app)
		let file = expand("%:p")
		echom "当前文件：" . file
		" 获取当前文件名，不带扩展名
		let filename = expand("%:r")
		echom "当前文件名(不带扩展名)" . filename
		" 获取当前文件名，不带扩展名
		let filepath = expand("%:p:h")
		echom "当前文件路径" . filepath
		
		let l:formats = {
			\"png":"png",
			\"svg":"svg",
			\}

		if(g:isWindows)
			let l:apps = {
				\"Chrome":"C\:\\Program Files\ \(x86\)\\Google\\Chrome\\Application\\chrome.exe",
				\"FireFox":"C\:\\Program\ Files\\Mozilla\ Firefox\\firefox.exe",
			\}
			" 执行命令用相应程序打开文件
			echom "执行命令，将当前文件".filepath."\\".filename.".".l:formats[a:format]."用".l:apps[a:app]."浏览器打开"
			execute "!start "  l:apps[a:app] filepath."\\".filename.".".l:formats[a:format]
		endif
		if(g:isLinux)
			let l:apps = {
				\"Chromium":"chromium",
				\"FireFox":"firefox",
				\}
			" 执行命令用相应程序打开文件
			echom "执行命令，将当前文件".filepath."/".filename.".".l:formats[a:format]."用".l:apps[a:app]."浏览器打开"
			execute "silent !"  l:apps[a:app] filepath."/".filename.".".l:formats[a:format]
		endif
	endfunction

	" 命令映射
	if(isWindows)
		:command PlantUMLSVG   :call XPlantUML("svg")        " 生成PlantUML的SVG
		:command PlantUMLPNG   :call XPlantUML("png")        " 生成PlantUML的PNG

		:command PlantUMLSVGFireFox    :call XPlantUMLViewer("svg","FireFox")       " 查看生成PlantUML的SVG
		:command PlantUMLPNGFireFox    :call XPlantUMLViewer("png","FireFox")       " 查看生成PlantUML的PNG
		:command PlantUMLSVGChrome     :call XPlantUMLViewer("svg","Chrome")        " 查看生成PlantUML的SVG
		:command PlantUMLPNGChrome     :call XPlantUMLViewer("png","Chrome")        " 查看生成PlantUML的PNG
	endif

	if(isLinux)
		:command PlantUMLSVG    :call XPlantUML("svg")        " 生成PlantUML的SVG
		:command PlantUMLPNG    :call XPlantUML("png")        " 生成PlantUML的PNG

		:command PlantUMLPNGChromium   :call XPlantUMLViewer("png","Chromium")        " 查看生成PlantUML的PNG
		:command PlantUMLSVGChromium   :call XPlantUMLViewer("svg","Chromium")        " 查看生成PlantUML的PNG
		:command PlantUMLSVGFireFox    :call XPlantUMLViewer("svg","FireFox")         " 查看生成PlantUML的SVG
		:command PlantUMLPNGFireFox    :call XPlantUMLViewer("png","FireFox")         " 查看生成PlantUML的PNG
		" :command PlantUMLSVGChrome     :call XPlantUMLViewer("svg","Chrome")        " 查看生成PlantUML的SVG
		" :command PlantUMLPNGChrome     :call XPlantUMLViewer("png","Chrome")        " 查看生成PlantUML的PNG
	
	endif

""""""""""""  自定义函数: 控制Fctix 模式切换时切换输入法
""""""""""""  
" 实现退出插入模式时自动关闭输入法。

	" let g:input_toggle = 1
    "
	" function! Fcitx2en()
	"    let s:input_status = system("fcitx-remote")
	"    if s:input_status == 2
	"       let g:input_toggle = 1
	"       let l:a = system("fcitx-remote -c")
	"    endif
	" endfunction
    "
	" function! Fcitx2zh()
	"    let s:input_status = system("fcitx-remote")
	"    if s:input_status != 2 && g:input_toggle == 1
	"       let l:a = system("fcitx-remote -o")
	"       let g:input_toggle = 0
	"    endif
	" endfunction
    "
	" set timeoutlen=150
	" autocmd InsertLeave * call Fcitx2en()

	" 实现进入插入模式自动启用输入法。
	"autocmd InsertEnter * call Fcitx2zh() "去掉这行行的注释可以，可以实现插入模式自动启动输入法

	" > 参考资料
		" - [第 10 章 通过命令控制Fcitx](http://fcitx.github.io/handbook/chapter-remote.html)

""""""""""""  自定义函数: 执行当前文件
""""""""""""  
" 在VIM中直接执行当前的脚本。执行之后的结果（屏幕输出）会被放在VIM窗口分屏之后的左边窗口内。
	" 版本一
	function! Setup_ExecNDisplay_v1()
	  execute "w"
	  execute "silent !chmod +x %:p"
	  let n=expand('%:t')
	  execute "silent !%:p 2>&1 | tee ~/.vim/output_".n
	  " I prefer vsplit
	  "execute "split ~/.vim/output_".n
	  execute "vsplit ~/.vim/output_".n
	  execute "redraw!"
	  set autoread
	endfunction

	" 版本二：
	function! Setup_ExecNDisplay()
		" 先保存更改
		execute "w"

		" echo &filetype 获取文件类型
		let filetype= expand(&filetype)

		" 获取文件名
		let n=expand('%:t')
		echom "当前 %:t ：" . n

		" 根据文件类型 使用不同应用执行
		if filetype == 'python'
			echom "文件类型是 .py python"
		elseif filetype == 'dosbatch'
		    echom "文件类型是 .bat"
		    " execute "silent !%:p 2>&1 | tee ~/.vim/output_".n
		elseif filetype == 'sh'
		    echo "文件类型是 .sh"
			" 授权执行权限
			execute "silent !chmod +x %:p"
			" 执行
		    execute "silent !%:p 2>&1 | tee ~/.vim/output_".n
		else
			" 授权执行权限
			execute "silent !chmod +x %:p"
			echo "其他情况，直接用终端执行"
		    execute "silent !%:p 2>&1 | tee ~/.vim/output_".n
		endif
		
		" 打开执行日志文件
		"execute "split ~/.vim/output_".n
		execute "vsplit ~/.vim/output_".n
		" 执行完刷新重绘制
	  	execute "redraw!"
	  	set autoread
	endfunction

	" 命令映射
		" 按 F5 键就可以执行
		:nmap <F5> :call Setup_ExecNDisplay()<CR>

	" 其他
		" 1):!command
		"   注释：不退出vim，并执行shell命令command，将命令输出显示在vim的命令区域，不会改变当前编辑的文件的内容
		" 2):r !command
		"   注释：将shell命令command的结果插入到当前行的下一行
		" 3):起始行号,结束行号 !command
		"   注释：将起始行号和结束行号指定的范围中的内容输入到shell命令command处理，并将处理结果替换起始行号和结束行号指定的范围中的内容
		" 4):起始行号,结束行号 w !command
		"   注释：将起始行号和结束行号所指定的范围的内容作为命令command的输入。不会改变当前编辑的文件的内容
		" 5):起始行号,结束行号 w !xargs command
		" 注释：将起始行号和结束行号所指定的范围的内容作为命令command的输入的命令行参数

		" 例:
		" :!ls -l
		" :r !date，读取系统时间并插入到当前行的下一行。
		" :62,72 !sort，将62行到72行的内容进行排序
		" :62 !tr [a-z] [A-Z]，将62行的小写字母转为大写字母
		" :62 w !bash，将会把第62行的内容作为bash命令来执行并显示结果，而且不会改变当前编辑的文件的内容，若62行内容为ls -l 那么输入:62 w !bash就跟执行!ls -l是一样的效果，如果你用的shell是bash shell
		" :. w !bash，将当前行（vim中光标所在行）的内容作为bash命令来执行,

	" > 参考资料
		" - [在VIM中直接将当前文件当做脚本执行的方法](https://blog.csdn.net/SH_UANG/article/details/53440511)
		" - [vim中执行shell命令小结](https://blog.csdn.net/songsong2017/article/details/83182674)
